#pragma once

#include "Extend.h"

#include "Constraint.h"
#include "ExtensionPoint.h"
#include "UseCase.h"

namespace uml {

Extend::Extend(const QString& umlType)
    : NamedElement(umlType) {}

void Extend::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    NamedElement::fromJson(json, errorList);
    DirectedRelationship::fromJson(json, errorList);
    condition_ = JsonSerializable::create<Constraint>(json.value("condition"), errorList);

    extendedCase_ = JsonSerializable::create<UseCase>(json.value("extendedCase"), errorList);

    extension_ = JsonSerializable::create<UseCase>(json.value("extension"), errorList);

    JsonSerializable::fromJsonArray(extensionLocations_, "extensionLocations", json, errorList);
}

void Extend::toJson(QJsonObject& json) {
    NamedElement::toJson(json);
    DirectedRelationship::toJson(json);
    if (condition_) {
        QJsonObject condition_json;
        condition_->toJson(condition_json);
        json.insert("condition", condition_json);
    }
    if (extendedCase_) {
        QJsonObject extendedCase_json;
        extendedCase_->toJson(extendedCase_json);
        json.insert("extendedCase", extendedCase_json);
    }
    if (extension_) {
        QJsonObject extension_json;
        extension_->toJson(extension_json);
        json.insert("extension", extension_json);
    }
    JsonSerializable::toJsonArray(extensionLocations_, "extensionLocations", json);
}

/// <summary>
/// condition getter
/// References the condition that must hold when the first ExtensionPoint is reached
/// for the extension to take place. If no constraint is associated with the Extend
/// relationship, the extension is unconditional.
/// </summary>
shared_ptr<Constraint> Extend::condition() const {
    return condition_;
}

/// <summary>
/// condition setter
/// References the condition that must hold when the first ExtensionPoint is reached
/// for the extension to take place. If no constraint is associated with the Extend
/// relationship, the extension is unconditional.
/// </summary>
void Extend::setCondition(shared_ptr<Constraint> value) {
    condition_ = value;
}

/// <summary>
/// extendedCase getter
/// The UseCase that is being extended.
/// </summary>
shared_ptr<UseCase> Extend::extendedCase() const {
    return extendedCase_;
}

/// <summary>
/// extendedCase setter
/// The UseCase that is being extended.
/// </summary>
void Extend::setExtendedCase(shared_ptr<UseCase> value) {
    extendedCase_ = value;
}

/// <summary>
/// extension getter
/// The UseCase that represents the extension and owns the Extend relationship.
/// </summary>
shared_ptr<UseCase> Extend::extension() const {
    return extension_;
}

/// <summary>
/// extension setter
/// The UseCase that represents the extension and owns the Extend relationship.
/// </summary>
void Extend::setExtension(shared_ptr<UseCase> value) {
    extension_ = value;
}

/// <summary>
/// extensionLocations getter
/// An ordered list of ExtensionPoints belonging to the extended UseCase, specifying
/// where the respective behavioral fragments of the extending UseCase are to be
/// inserted. The first fragment in the extending UseCase is associated with the
/// first extension point in the list, the second fragment with the second point,
/// and so on. Note that, in most practical cases, the extending UseCase has just a
/// single behavior fragment, so that the list of ExtensionPoints is trivial.
/// </summary>
vector<shared_ptr<ExtensionPoint>>& Extend::extensionLocations() {
    return extensionLocations_;
}

} // namespace uml
